package physics;

import java.awt.event.ActionEvent;

import physics.Collisions.Collision;
import physics.MovementControl.MissileMovementController;

import common.Math3D;
import common.Point3D;

public class Missile extends Weapon {


	private double step = 0.2;
	private Robot target=null;
	private int ticksToFall;
	private int ticksToStartAiming;
	
	public Missile(){
		ticksToDisappear = 20;
		ticksToFall = 60;
		ticksToStartAiming = 10;
		this.setMovementControler(new MissileMovementController(this));
		this.getMovementControler().setHasMomentum(true);	
		this.getMovementControler().setMovementLimit(0.4);
		this.getMovementControler().setRotationLimit(0.15);
		this.getMovementControler().setRotationFriction(0.01);
		ticks = 0;
	}


	public void clockTicked(ActionEvent arg0) {
		
		ticksToStartAiming--;
		if (!disappearing){
			this.getMovementControler().setMovement(Math3D.scalePoint(getFace(), step));

			if (target != null){
				rotateTo(target);
			}
			
			if (!this.getMovementControler().inTheAir()){
				//System.out.println("exploded");
				explode();
			}

		}
		if (ticks++ >= ticksToFall ){
			ticks = 0;
			disappearing = true;
		}
		super.clockTicked(arg0);


	}


	public void impact(Collision c){

		GameObject bumpedInto;	
		if (c.getObj1().equals(this))
			bumpedInto= c.getObj2();
		else
			bumpedInto = c.getObj1();


		switch (c.getType()){
		case MESSILEROBOT:
			if ( !((Robot)bumpedInto).disappearing){
				if (target == null){
					target = ((Robot)bumpedInto);
				}
				else{
					double curdistance = Math3D.getDistance(target.getCenter(), this.getCenter());
					double bumdistance = Math3D.getDistance(bumpedInto.getCenter(), this.getCenter());
					if (bumdistance < curdistance)
						target = ((Robot)bumpedInto);
				}
				rotateTo(target);
			}
			if (target != null && ((Robot)bumpedInto).inHittingRange(getCenter())){
				explode();
			}				
			this.setMoved(true);
			break;
		}
	}

	boolean aimAngleXY;
	private void rotateTo(GameObject target) {
		if (ticksToStartAiming > 0) return;
		if (aimAngleXY)
		{
			Point3D targetVector = Math3D.subPoint(target.getCenter(), this.getCenter());
			Point3D fixVector =
				Math3D.scalePoint(this.getUp(), 
						Math3D.getDotProduct(targetVector, this.getUp()));
			targetVector.sub(fixVector);
			targetVector.normalize();

			double angle = Math.acos(Math3D.getDotProduct(targetVector, this.getFace()));
			if (Math3D.getDotProduct(targetVector, this.getLeft()) < 0)
				angle = -angle;

			if (!Double.isNaN(angle)){
				this.getMovementControler().rotationY(angle);
			}
		}
		else{
			Point3D targetVector = Math3D.subPoint(target.getCenter(), this.getCenter());
			Point3D fixVector =
				Math3D.scalePoint(this.getLeft(), 
						Math3D.getDotProduct(targetVector, this.getLeft()));
			targetVector.sub(fixVector);
			targetVector.normalize();

			double angle = Math.acos(Math3D.getDotProduct(targetVector, this.getFace()));
			if (Math3D.getDotProduct(targetVector, this.getUp()) < 0)
				angle = -angle;

			if (!Double.isNaN(angle)){
				this.getMovementControler().rotationX(angle);
			}
		}
		aimAngleXY = !aimAngleXY;
	}

	
	public void fire(){
		getMovementControler().setMovement(
				Math3D.addPoint(
						position.getUp(),position.getFace())
		);
	}

}


